﻿// Serotonin -- easy-to-use image filters application
// https://code.google.com/p/serotonin/
//
// Copyright © Frank Nagl, 2012-2013
// admin@franknagl.de
//
namespace Serotonin.Helper
{
    using System.Collections.Generic;
    using System.Drawing;
    using System.Drawing.Drawing2D;

    /// <summary> Represents a polygon figure in an image. </summary>
    public class Figure
    {
        private readonly Color color; 
        private readonly int lineStrength;
        private readonly GraphicsPath path;

        /// <summary> Corner points of the polygon figure. </summary>
        public List<Point> Corners { get; private set; } 

        /// <summary>
        /// Initializes a new instance of the <see cref="Figure"/> class.
        /// </summary>
        /// <param name="color">The color of the figure.</param>
        public Figure(Color color)
        {
            this.color = color;
            Corners = new List<Point>();
            path = new GraphicsPath();            
            lineStrength = 2;
        }

        /// <summary>
        /// Adds the specified point as corner of the figure.
        /// </summary>
        /// <param name="pt">The point to add.</param>
        public void AddCorner(Point pt)
        {            
            Corners.Add(pt);
            
            // RefillPathWithCorners
            path.Reset();
            switch (Corners.Count)
            {
                case 1:
                    return;
                case 2:
                    path.AddLine(Corners[0], Corners[1]);
                    break;
                default:
                    Point[] array = new Point[Corners.Count];
                    for (int i = 0; i < Corners.Count; i++)
                    {
                        array[i] = Corners[i];
                    }
                    path.AddPolygon(array);
                    break;
            }
        }

        /// <summary>
        /// Checks, if the given point is inside the object.
        /// </summary>
        public virtual bool Contains(int x, int y)
        {
            return path.IsVisible(x, y);
        }

        /// <summary> Draws the figure into the specified graphics object. </summary>
        /// <param name="graphics">The graphics object to use for drawing.</param>
        public virtual void Draw(
            Graphics graphics)
        {
            graphics.DrawPath(new Pen(color, lineStrength), path);
        }  

        /// <summary>Fills the figure into the specified graphics object.</summary>
        /// <param name="graphics">The graphics object to use for filling.</param>
        /// <param name="transpacency">The transpacency value for filling.</param>
        public virtual void Fill(
            Graphics graphics,
            int transpacency = 128)
        {
            graphics.FillPath(
                new SolidBrush(Color.FromArgb(transpacency, color)),
                path);
        }      

        /// <summary> Resets the figure's path and corner points. </summary>
        public virtual void Reset()
        {
            path.Reset();
            Corners.Clear();
        }

        /// <summary>
        /// Scales the figure with specified scale factors for
        /// x-direction (horizontal) and y-direction (vertical).
        /// </summary>
        public virtual void Scale(float scaleX, float scaleY)
        {
            for (int i = 0; i < Corners.Count; i++)
            {
                Point pt = Corners[i];
                pt.X = (int)(pt.X * scaleX + 0.5f);
                pt.Y = (int)(pt.Y * scaleY + 0.5f);
                Corners[i] = pt;
            }

            Matrix mat = new Matrix();
            mat.Scale(scaleX, scaleY);
            path.Transform(mat);
        }

        /// <summary>
        /// Moves the figure <param name="deltaX" /> pixel in 
        /// x-direction (horizontal) and <param name="deltaY" /> pixel in 
        /// y-direction (vertical).
        /// </summary>
        public virtual void Translate(int deltaX, int deltaY)
        {
            Matrix mat = new Matrix();
            mat.Translate(deltaX, deltaY);
            path.Transform(mat);
        }

        //public void Print()
        //{
        //    Console.WriteLine("CORNER X: Corners-List" + "\t" + "Path-List\n");
        //    for (int i = 0; i < Corners.Count; i++)
        //    {
        //        Point pt = Corners[i];
        //        PointF pf = path.PathPoints[i];
        //        Console.WriteLine("Corner " + i + ": " + pt + "\t" + pf);
        //    }
        //}
    }
}
